﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
using Nasa8x.Core;
using Nasa8x.Mvc.Helpers;
using Nasa8x.Wrapper.IO;

namespace Nasa8x.Mvc.Controls
{
    public abstract class IZipController : Controller
    {
        private readonly IFileWrap file;

        protected IZipController()
        {
            file = new FileWrap();
        }

        private string DecodeAndMapPath(string path)
        {
            string decoded = Server.UrlDecode(path);
            string mapped = Server.MapPath(decoded);
            return mapped;
        }

        private IEnumerable<string> DecodeAndMapPaths(string paths)
        {
            string[] _pathList = paths.Split('|');
            return _pathList.Select(n => DecodeAndMapPath(n));
        }

        private void SetupDefaultCaching()
        {
            Response.Cache.SetCacheability(HttpCacheability.Public);
            Response.Cache.SetExpires(Cache.NoAbsoluteExpiration);
            Response.Cache.SetLastModifiedFromFileDependencies();
        }

        public virtual void Image(string path, bool? cache)
        {
            //get md5 key
            string key = MD5.Encode(path);

            //get mapped path
            string mappedPath = DecodeAndMapPath(path);

            //try to get image from cache
            var image = CacheWrapper.Get(key) as byte[];

            //if image isn't in cache, open the file
            if (image == null)
            {
                //get bytes from file
                image = file.ReadAllBytes(mappedPath);

                //insert image bytes into cache
                if (cache != false) CacheWrapper.Add(key, image, mappedPath, 10);
            }

            //write bytes to response
            Response.ContentType = "image/jpeg";
            Response.OutputStream.Write(image, 0, image.Length);
            Response.Cache.SetETag("\"" + key + "\"");

            //add file dependency
            Response.AddFileDependency(mappedPath);

            //add image to response cache
            if (cache != false) SetupDefaultCaching();

            //send response to the client
            Response.Flush();
        }

        
        public virtual void Style(string paths, bool? cache)
        {
            string key = MD5.Encode(paths);
            var utf8 = CacheWrapper.Get(key) as string;
            string[] pathList = DecodeAndMapPaths(paths).ToArray();

            if (utf8 == null)
            {
                var text = new StringBuilder();
                foreach (string path in pathList)
                {
                    string fileText = file.ReadAllText(path);

                    text.Append(fileText);
                    text.Append(Environment.NewLine);
                }

                utf8 = text.ToString();
                if (cache != false) CacheWrapper.Add(key, utf8, pathList, 10);
            }

            //write bytes to response
            Response.ContentType = "text/css";
            Response.Cache.SetETag("\"" + key + "\"");

            //add file dependency
            Response.AddFileDependencies(pathList);

            //add image to response cache
            if (cache != false) SetupDefaultCaching();

            //send response to the client
            Response.Write(utf8);
            Response.Flush();
        }

        
        public virtual void Script(string paths, bool? cache)
        {
            string key = MD5.Encode(paths);
            var utf8 = CacheWrapper.Get(key) as string;
            string[] pathList = DecodeAndMapPaths(paths).ToArray();

            if (utf8 == null)
            {
                var text = new StringBuilder();
                foreach (string path in pathList)
                {
                    string fileText = file.ReadAllText(path);
                    text.Append(fileText);
                    text.Append(Environment.NewLine);
                }

                utf8 = text.ToString();
                if (cache != false) CacheWrapper.Add(key, utf8, pathList, 10);
            }

            //write bytes to response
            Response.ContentType = "application/x-javascript";
            Response.Cache.SetETag("\"" + key + "\"");

            //add file dependency
            Response.AddFileDependencies(pathList);

            //add image to response cache
            if (cache != false) SetupDefaultCaching();

            //send response to the client
            Response.Write(utf8);
            Response.Flush();
        }
    }
}